package modelDeLivreur;

import java.io.File;
import java.util.Iterator;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
 
import model.TravelPath;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import utils.UrlUtils;
 
public class GDParser {
 
	
	/**
	 * Wrapper function allowing to extract a specific trajectory's information
	 * provided by the Google Directions web service.
	 * 
	 * @param urlStr String used to obtain information from the Google Directions web service
	 * @return TravelPath Wrapper object containing all relevant information to specfied trajectory
	 * @throws Exception
	 */
	public TravelPath getTravelPath(String urlStr) throws Exception{
		TravelPath tp = new TravelPath();
		downLoadXML(urlStr);
		Document doc = loadXML();
		tp = setDirections(doc, tp);
		tp = setTravelPoints(doc, tp);
		return tp;
	}
	
	/**
	 * Method that dowloads information from the Google Directions web service
	 * 
	 * @param urlStr
	 * @return boolean
	 */
	private boolean downLoadXML(String urlStr){
		return UrlUtils.readCopyHttpResponse("temp.xml", urlStr);
	}
	
	/**
	 * Method that loads the contents of the dowloaded XML file 
	 * into an XML Documnent.
	 * 
	 * @return Document Object representing the actual downloaded XML document
	 * @throws Exception
	 */
	private Document loadXML()throws Exception{
		Document doc = null;
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        File file = new File("temp.xml");
        if (file.exists()) {
        	doc = db.parse(file);
        }
        return doc; 
	}
	
	/**
	 * Method that parses the XML Document (doc), extracting the directions and adding them
	 * to the TravelPath object.
	 * 
	 * @param doc Represents the XML document
	 * @param tp Represent the TravelPath object
	 * @return TravelPath
	 */
	private TravelPath setDirections(Document doc, TravelPath tp){
		
		Element docEle = doc.getDocumentElement();
		
		// Extract all the steps for the trajectory
		// The instructions, individual duration and distance values are 
		// child nodes to the step node
		
		NodeList directionsList = docEle.getElementsByTagName("step");
		if (directionsList != null && directionsList.getLength() > 0) {
            for (int i = 0; i < directionsList.getLength(); i++) {

                Node node = directionsList.item(i);

                if (node.getNodeType() == Node.ELEMENT_NODE) {

                	String htmlInstruction = null;
                	String duration = null;
                	String distance = null;
                    
                    Element e = (Element) node;
                    
                    NodeList nodeList = e.getElementsByTagName("html_instructions");
                    htmlInstruction = nodeList.item(0).getChildNodes().item(0).getNodeValue();

                    nodeList = e.getElementsByTagName("distance");
                    Element el = (Element)nodeList.item(0);
                    NodeList nl2 = el.getElementsByTagName("text");
                    distance = nl2.item(0).getChildNodes().item(0).getNodeValue();
                    
                    nodeList = e.getElementsByTagName("duration");
                    Element el2 = (Element)nodeList.item(0);
                    NodeList nl3 = el2.getElementsByTagName("text");
                    duration = nl3.item(0).getChildNodes().item(0).getNodeValue();
                    
                    tp.addDirection(htmlInstruction, duration, distance);
                                    
                }
            }
        }
		
		return tp;
	}
	
	/**
	 * Method that parses the XML Document (doc), extracting the start address, end address and waypoit of the 
	 * specified trajectory. The results are added to the TravelPath object
	 * 
	 * @param doc Represents the XML document
	 * @param tp Represent the TravelPath object
	 * @return TravelPath
	 */
	private TravelPath setTravelPoints(Document doc, TravelPath tp){
		
		Element docEle = doc.getDocumentElement();
		NodeList legList = docEle.getElementsByTagName("leg");
		
		Element e1 = (Element)legList.item(0);
		tp.setStartLocation(e1.getElementsByTagName("start_address").item(0).getChildNodes().item(0).getNodeValue());
		tp.setWayPoint(e1.getElementsByTagName("end_address").item(0).getChildNodes().item(0).getNodeValue());
		
		Element e2 = (Element)legList.item(1);
		tp.setEndLocation(e2.getElementsByTagName("end_address").item(0).getChildNodes().item(0).getNodeValue());
	
		return tp;
	}
	

    public static void main(String[] args) throws Exception{
 
        GDParser parser = new GDParser();
        TravelPath tp = parser.getTravelPath("http://maps.googleapis.com/maps/api/directions/xml?origin=39%20gauthier,&20dollard-des-ormeaux,%20quebec,%20h9g1z6,%20canada&destination=4649%20de%20la%20peltrie,%20montreal,%20quebec,%20h3w1k4,%20canada&waypoints=8570%20bloomfield,%20montreal,%20quebec,%20h3n2j3,%20canada&optimize=true&sensor=false");
    
        System.out.println(tp.getStartLocation());
        System.out.println(tp.getWayPoint());
        System.out.println(tp.getEndLocation());
    
        Iterator<Direction>it = tp.iterator();
        for(;it.hasNext();){
        	System.out.println(it.next().toString());
        	System.out.println();
        }
        
        
        
        
        System.out.println(tp.getTotalDistance()+" km");
        System.out.println(tp.getTotalDuration()+ " min");
        System.out.println();
    
    
    
    
    
    
    
    
    
    }
}
